#pragma once

#include "surface.h"

namespace App
{

struct LibData;
struct Event;

class Application
{
    public:
        Application();

        int OnExecute();
		void OnExit();
		void SetVideoMode(int width, int height);
		void GetVideoMode(int& width, int& height);
		void SetAppName(const char* name);

		Render::SurfacePtr MainView();

		float GetFrameTimeMs() const;
		float GetUpdateTimeMs() const;
		float GetRenderTimeMs() const;
		uint32 GetFrameCount() const;

    private:
        bool OnInit_();
        void OnUpdate_();
        void OnRender_();
        void OnCleanup_();

		virtual bool OnInit() {return true;}
		virtual void OnUpdate() {};
		virtual void OnRender() {};
		virtual void OnCleanup() {};
		virtual void OnEvent(const Event* pEvent) {}

		int m_videoWidth;
		int m_videoHeight;

		bool m_running;

		float m_updateTimeMs;
		float m_renderTimeMs;
		float m_frameTimeMs;
		uint32 m_frameCount;

		std::string m_appName;

		Ut::SharedPtr<LibData> m_pLibData;
};

// Input ///////////////////////////////////////////////////////////////////////

enum KeyCode
{
	KEY_A,
	KEY_B,
	KEY_C,
	KEY_D,
	KEY_E,
	KEY_F,
	KEY_G,
	KEY_H,
	KEY_I,
	KEY_J,
	KEY_K,
	KEY_L,
	KEY_M,
	KEY_N,
	KEY_O,
	KEY_P,
	KEY_Q,
	KEY_R,
	KEY_S,
	KEY_T,
	KEY_U,
	KEY_V,
	KEY_W,
	KEY_X,
	KEY_Y,
	KEY_Z,

	KEY_0,
	KEY_1,
	KEY_2,
	KEY_3,
	KEY_4,
	KEY_5,
	KEY_6,
	KEY_7,
	KEY_8,
	KEY_9,

	KEY_PAD_0,
	KEY_PAD_1,
	KEY_PAD_2,
	KEY_PAD_3,
	KEY_PAD_4,
	KEY_PAD_5,
	KEY_PAD_6,
	KEY_PAD_7,
	KEY_PAD_8,
	KEY_PAD_9,

	KEY_F1,	
	KEY_F2,	
	KEY_F3,	
	KEY_F4,	
	KEY_F5,	
	KEY_F6,	
	KEY_F7,	
	KEY_F8,	
	KEY_F9,	
	KEY_F10,	
	KEY_F11,	
	KEY_F12,	

	KEY_ESCAPE,		
	KEY_TILDE,		
	KEY_MINUS,		
	KEY_EQUALS,		
	KEY_BACKSPACE,	
	KEY_TAB,			
	KEY_OPENBRACE,	
	KEY_CLOSEBRACE,	
	KEY_ENTER,		
	KEY_SEMICOLON,	
	KEY_QUOTE,		
	KEY_BACKSLASH,	
	KEY_BACKSLASH2,	
	KEY_COMMA,		
	KEY_FULLSTOP,	
	KEY_SLASH,		
	KEY_SPACE,		

	KEY_INSERT,	
	KEY_DELETE,	
	KEY_HOME,	
	KEY_END,		
	KEY_PGUP,	
	KEY_PGDN,	
	KEY_LEFT,	
	KEY_RIGHT,	
	KEY_UP,		
	KEY_DOWN,	

	KEY_PAD_SLASH,	
	KEY_PAD_ASTERISK,
	KEY_PAD_MINUS,	
	KEY_PAD_PLUS,	
	KEY_PAD_DELETE,	
	KEY_PAD_ENTER,	

	KEY_LSHIFT,	
	KEY_RSHIFT,	
	KEY_LCTRL,	
	KEY_RCTRL,	
	KEY_ALT,		
	KEY_ALTGR,	
	KEY_LWIN,
	KEY_RWIN,
	KEY_MENU,	
	KEY_SCROLLLOCK,
	KEY_NUMLOCK,
	KEY_CAPSLOCK,

	KEY_UNKNOWN
};

struct MouseState
{
	int x;
	int y;
	bool left;
	bool right;
};

const MouseState& GetMouseState();

bool KeyDown(KeyCode keyCode);

enum EventType
{
	EVENT_UNKNOWN,
	EVENT_KEY_DOWN,
};

EventType GetType(const Event* pEvent);

struct KeyDownEvent
{
	uint16 unicode;
	KeyCode keyCode;
};

KeyDownEvent GetKeyDownEvent(const Event* pEvent);

class Section
{
public:
	Section() : m_running(false) {}
	virtual ~Section() {}

	virtual bool OnInit(Application* pApp) {return true;}
	virtual void OnUpdate(float timeStep) {}
	virtual void OnRender(Render::SurfacePtr pSurface) {}
	virtual void OnCleanup() {}
	virtual void OnExit() {m_running = false;}
	virtual void OnEvent(const Event* pEvent) {}

	void Activate() {m_running = true;}
	bool IsRunning() const {return m_running;}

private:
	bool m_running;
};

}

